package com.sicau.socialpracticesystem.util.upload;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.function.Function;

/**
 * 通用easyExcel的listener，用于生产各种业务的listener
 *
 * @author ：xiongtao
 */
@Slf4j
public class ExcelListenerHelper<T> {

    /**
     * 成功导入数量
     */
    private Integer successCount = 0;

    /**
     * 失败结果集
     */
    private List<ExcelCheckErrDto<T>> errList = new ArrayList<>();

    /**
     * 不限定批处理阈值
     *
     * @param function  读取数据后需要做的事情
     * @param threshold 批处理阈值
     * @return com.alibaba.excel.event.AnalysisEventListener
     */
    public AnalysisEventListener<T> getListener(Function<List<T>, Integer> function, int threshold) {
        return new AnalysisEventListener<T>() {

            List<T> list = new LinkedList<>();

            Integer tempRow = 0;

            /**
             * 这个每一条数据解析都会来调用
             */
            @Override
            public void invoke(T data, AnalysisContext analysisContext) {
                log.info("解析到一条数据:{}", JSON.toJSONString(data));

                List<ExcelCheckErrDto<T>> invokeErrList = null;
                tempRow++;
                try {
                    //根据excel数据实体中的javax.validation + 正则表达式来校验excel数据
                    invokeErrList = ValidateHelper.validateEntity(data, tempRow);
                } catch (NoSuchFieldException e) {
                    log.error("解析数据出错", e);
                    ExcelCheckErrDto<T> errDto = new ExcelCheckErrDto<>(data, "解析数据出错");
                    errDto.setRow(tempRow);
                    errList.add(errDto);
                    return;
                }

                if (invokeErrList == null || invokeErrList.size() == 0) {
                    list.add(data);
                } else {
                    errList.addAll(invokeErrList);
                    return;
                }

                if (list.size() >= threshold) {
                    Integer success = function.apply(list);
                    successCount += success;
                    list.clear();
                }
            }

            /**
             * 所有数据解析完成了 都会来调用
             */
            @Override
            public void doAfterAllAnalysed(AnalysisContext analysisContext) {
                if (list.size() > 0) {
                    Integer success = function.apply(list);
                    successCount += success;
                }
                log.info("所有数据解析完成");
            }
        };
    }

    /**
     * 限定批处理阈值
     */
    public AnalysisEventListener<T> getListener(Function<List<T>, Integer> function) {
        return getListener(function, 200);
    }

    /**
     * 获取成功数量
     */
    public Integer getSuccessCount() {
        return successCount;
    }

    /**
     * 获取失败集合
     */
    public List<ExcelCheckErrDto<T>> getErrList() {
        return errList;
    }

    /**
     * 外部向errList添加
     */
    public void addErrDto(ExcelCheckErrDto<T> errDto) {
        errList.add(errDto);
    }

}
